<template>
  <canvas canvas-id="myCanvas" disable-scroll :style="drawPadStyles" @touchstart="onTouchStart"
          @touchmove="onTouchMove" @touchend="onTouchEnd" />
</template>

<script>

function deepClone(data) {
  return JSON.parse(JSON.stringify(data))
}

export default {
  props: {
    width: {
      type: Number,
      required: true
    },
    height: {
      type: Number,
      required: true
    },
    color: {
      type: String,
      default: '#000'
    },
    size: {
      type: Number,
      default: 3
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },

  computed: {
    drawPadStyles({
                    width,
                    height
                  }) {
      return `width: ${width}px;height: ${height}px`
    }
  },

  methods: {
    onTouchStart(e) {
      const {
        disabled,
        points,
        originData
      } = this
      if (disabled) return
      const {
        x,
        y
      } = e.changedTouches[0]
      points.push([x, y])
      originData.push([
        [x, y]
      ])
    },
    onTouchMove(e) {
      const {
        disabled,
        points,
        originData,
        draw
      } = this
      if (disabled) return
      const {
        x,
        y
      } = e.changedTouches[0]
      points.push([x, y])
      originData[originData.length - 1].push([x, y])
      draw()
    },
    onTouchEnd() {
      this.points = []
    },
    draw() {
      const {
        ctx,
        points
      } = this
      if (points.length < 2) return
      ctx.moveTo(...points.shift())
      ctx.lineTo(...points[0])
      ctx.stroke()
      ctx.draw(true)
    },
    /**
     * 清空画布
     */
    init() {
      const {
        ctx,
        width,
        height
      } = this
      ctx.clearRect(0, 0, width, height)
      ctx.draw()
      this.originData = []
    },
    /**
     * 回退到上一笔
     */
    back() {
      const {
        originData,
        drawByData
      } = this
      originData.pop()
      drawByData(originData)
    },
    /**
     * 根据传入的数据绘制
     * @param {Array} data
     */
    drawByData(data) {
      const {
        init,
        ctx
      } = this
      if (!data || !data.length) return init()
      const tempData = deepClone(data)
      while (!!tempData.length) {
        const lineData = tempData.shift()
        ctx.moveTo(...lineData.shift())
        while (!!lineData.length) ctx.lineTo(...lineData.shift())
      }
      ctx.stroke()
      ctx.draw()
    },
    /**
     * 临时保存画布上的数据
     * @param {Any} key 用于访问的key
     * @param {Boolean} isInit 保存完毕后是否清空画布，默认为true
     */
    saveCache(key, isInit = true) {
      const {
        cache,
        originData,
        init
      } = this
      const temp = deepClone(originData)
      cache.set(key, temp)
      if (isInit) init()
    },
    /**
     * 用缓存的key恢复画布
     * @param {Any} key 用于访问的key
     */
    restoreCache(key) {
      const {
        drawByData,
        cache
      } = this
      this.originData = cache.get(key)
      drawByData(this.originData)
    },
    /**
     * 清空缓存数据
     */
    clearCache() {
      this.cache.clear()
    },
    save(options) {
      return new Promise((success, fail) => {
        const {
          width,
          height,
          canvasId
        } = this
        uni.canvasToTempFilePath({
              x: 0,
              y: 0,
              width,
              height,
              ...options,
              canvasId: 'myCanvas',
              success,
              fail
            },
            this
        )
      })
    }
  },

  created() {
    const {
      color,
      size
    } = this
    const ctx = uni.createCanvasContext('myCanvas', this)
    ctx.setStrokeStyle(color)
    ctx.setLineWidth(size)
    ctx.setLineCap('round')
    ctx.setLineJoin('round')
    this.ctx = ctx
    this.points = []
    this.originData = []
    this.cache = new Map()
  }
}
</script>
